package cmd

import (
	"fmt"
	"os"
	"sort"

	"github.com/urfave/cli/v2"
)

type command struct {
	opts Options
	app  *cli.App
}

var (
	DefaultCmd = New()
)

func (c *command) App() *cli.App {
	return c.app
}

func New(opts ...Option) *command {
	options := Options{}
	for _, o := range opts {
		o(&options)
	}
	cmd := new(command)
	cmd.opts = options
	cmd.app = cli.NewApp()

	return cmd
}

func (c *command) Run() error {
	defer func() {
		if r := recover(); r != nil {
			panic(r)
		}
	}()
	return c.app.Run(os.Args)
}

func Register(cmds ...*cli.Command) {
	app := DefaultCmd.App()
	app.Commands = append(app.Commands, cmds...)
	sort.Slice(app.Commands, func(i, j int) bool {
		return app.Commands[i].Name < app.Commands[j].Name
	})
}

func Run() {
	if err := DefaultCmd.Run(); err != nil {
		fmt.Println(err)
		os.Exit(1)
	}
}
